package com.ygq.Impl;

import BO.AddFillEmptyAnswersBO;
import BO.AnswerBO;
import DO.FillEmptyAnswerDO;
import DO.FillEmptyDO;
import DTO.AddFillEmptyDTO;
import DTO.PageJudgeQuestionDTO;
import DTO.UpdateFillEmptyQuestionDTO;
import VO.FillEmptyVO;
import com.ygq.FillEmptyQuestionService;
import mapper.FillEmptyAnswerQuestionMapper;
import mapper.FillEmptyQuestionMapper;
import mapper.WorkFillMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import result.PageResult;

import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class FillEmptyQuestionServiceImpl implements FillEmptyQuestionService {

    @Autowired
    private FillEmptyQuestionMapper fillEmptyQuestionMapper;

    @Autowired
    private FillEmptyAnswerQuestionMapper fillEmptyAnswerQuestionMapper;

    @Autowired
    private WorkFillMapper workFillMapper;


    /**
     * 分页查询
     * @param pageFillEmptyQuestionDTO
     * @return
     */
    public PageResult page(PageJudgeQuestionDTO pageFillEmptyQuestionDTO) {
        PageResult pageResult = new PageResult();
        // 第一次查询 查询总数
        Integer total = fillEmptyQuestionMapper.getTotal(pageFillEmptyQuestionDTO);

        // 第二次查询 查询分页数据
        /*
         * 这里将getCurrentPage作为 (currentPage - 1) * pageSize;
         */
        pageFillEmptyQuestionDTO.setCurrentPage( (pageFillEmptyQuestionDTO.getCurrentPage() - 1) * pageFillEmptyQuestionDTO.getPageSize());
        List<FillEmptyDO> list = fillEmptyQuestionMapper.page(pageFillEmptyQuestionDTO);
        List<FillEmptyVO> fillEmptyVOS = new ArrayList<>();

        // 这个list还不能使用，还要使用这个list里面的地址将代码片段查询出来,
        // 还要利用提出list里面的题目id，利用这个题目id，去答案表查询数据封装到fillEmptyVOS这个集合

        // 其他元素先赋值到fillEmptyVOS，还差代码片段和答案
        for (int i = 0; i < list.size(); i++) {
            // new 一个FillEmptyVO对象， 存储单个试题信息
            FillEmptyVO fillEmptyVO = new FillEmptyVO();
            BeanUtils.copyProperties(list.get(i),fillEmptyVO);

            // 根据地址，获取到代码文本，将代码文本保存到 fillEmptyVO 单项中
            String address = list.get(i).getAddress();
            try {
                String code = readFileToString(address);
                fillEmptyVO.setCode(code);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            // 获取答案集合
            // 首先， 创建一个答案集合
            List<AnswerBO> answerBOList =fillEmptyAnswerQuestionMapper.getAnswerByFEId(fillEmptyVO.getId());
            // 根据题目id从FillEmptyAnswer表中获取答案数据
            fillEmptyVO.setAnswers(answerBOList);
            // 将这个单项加入到list集合中
            fillEmptyVOS.add(fillEmptyVO);
        }

        pageResult.setTotal(total);
        pageResult.setRecords(fillEmptyVOS);
        return pageResult;
    }

    /**
     * 程序阅读题
     * @param addFillEmptyDTO
     */
    @Transactional
    public void addQuestion(AddFillEmptyDTO<AddFillEmptyAnswersBO> addFillEmptyDTO,String path) {
        String fillName = addFillEmptyDTO.getQuestionNumber()+".txt";
        // 第一步，将code添加到一个txt文件
        saveToFile(addFillEmptyDTO.getCode(),fillName,path);
        // 第二步，添加主要信息
        FillEmptyDO fillEmptyDO=new FillEmptyDO();
        BeanUtils.copyProperties(addFillEmptyDTO,fillEmptyDO);
        // 补充必要字段
        fillEmptyDO.setAddress(path+fillName);
        fillEmptyDO.setAnswerNumber(addFillEmptyDTO.getAnswers().size());
        fillEmptyDO.setCreateTime(LocalDateTime.now());
        fillEmptyQuestionMapper.addQuestion(fillEmptyDO);

        // 第三步，添加答案信息
        List<FillEmptyAnswerDO> fillEmptyAnswerDOList = new ArrayList<>();
        for (int i = 0; i < addFillEmptyDTO.getAnswers().size(); i++) {
            FillEmptyAnswerDO fillEmptyAnswerDO = new FillEmptyAnswerDO();
            fillEmptyAnswerDO.setFillEmptyId(fillEmptyDO.getId());//设置题目id
            fillEmptyAnswerDO.setOrder(addFillEmptyDTO.getAnswers().get(i).getOrder());// 设置序号
            fillEmptyAnswerDO.setAnswer(addFillEmptyDTO.getAnswers().get(i).getAnswer());//设置答案
            fillEmptyAnswerDO.setCreateTime(LocalDateTime.now());//设置创建时间
            fillEmptyAnswerDOList.add(fillEmptyAnswerDO);
        }
        // 向list集合添加完数据之后，执行mapper
        fillEmptyAnswerQuestionMapper.addQuestionAnswers(fillEmptyAnswerDOList);
    }

    /**
     * 获取所有编号
     * @return
     */
    public List<String> getQuestionNumber() {
        return fillEmptyQuestionMapper.getQuestionNumber();
    }

    // 检验数据
    public Integer check(UpdateFillEmptyQuestionDTO updateFillEmptyQuestionDTO) {
        int isRelevancyWork = workFillMapper.getIsRelevancyWork(updateFillEmptyQuestionDTO.getId());
        List<AnswerBO> answer = fillEmptyAnswerQuestionMapper.getAnswerByFEId(updateFillEmptyQuestionDTO.getId());
        if(answer.size() != updateFillEmptyQuestionDTO.getAnswers().size()){
            // 表示答案数量发生变化，返回
            if (isRelevancyWork >0){
                // 表示关联了试卷，不能删除
                return 1;
            }
        }
        for (int i = 0; i < Math.min(answer.size(), updateFillEmptyQuestionDTO.getAnswers().size()); i++) {
            if (answer.get(i).getAnswer() != updateFillEmptyQuestionDTO.getAnswers().get(i).getAnswer()){
                // 答案发生变化
                if (isRelevancyWork >0){
                    // 表示关联了试卷，不能删除
                    return 1;
                }
            }
        }
        return 0;
    }

    /**
     * 更新题目
     */
    @Transactional
    public void updateQuestion(UpdateFillEmptyQuestionDTO updateFillEmptyQuestionDTO,String path) {
        // 更新分三步，第一步，常规更新，题目描述。第二步 答案更新（先删除有id的答案，再插入答案数据），第三步更新代码块
        fillEmptyQuestionMapper.updata(updateFillEmptyQuestionDTO);
        // 第二步，先在答案表里面删除题目id的所有字段
        fillEmptyAnswerQuestionMapper.deleteByFillEmptyId(updateFillEmptyQuestionDTO.getId());
        // 然后再插入新答案
        List<FillEmptyAnswerDO> fillEmptyAnswerDOList = new ArrayList<>();
        for (AnswerBO answer : updateFillEmptyQuestionDTO.getAnswers()) {
            FillEmptyAnswerDO fillEmptyAnswerDO = new FillEmptyAnswerDO();
            fillEmptyAnswerDO.setFillEmptyId(updateFillEmptyQuestionDTO.getId());
            fillEmptyAnswerDO.setOrder(answer.getOrder());
            fillEmptyAnswerDO.setCreateTime(LocalDateTime.now());
            fillEmptyAnswerDO.setAnswer(answer.getAnswer());
            fillEmptyAnswerDOList.add(fillEmptyAnswerDO);
        }
        fillEmptyAnswerQuestionMapper.addQuestionAnswers(fillEmptyAnswerDOList);

        // 第三步 ，更新代码片段文件
        String fillName = updateFillEmptyQuestionDTO.getQuestionNumber()+".txt";
        // 然后将code添加到一个txt文件
        saveToFile(updateFillEmptyQuestionDTO.getCode(),fillName,path);
    }

    // 删除题目
    @Transactional
    public void deleteById(Integer id) {
        // 这里不需要清除代码片段文件。下一次这个编号添加题目的时候会自动覆盖这个文件
        fillEmptyQuestionMapper.deleteById(id);
        fillEmptyAnswerQuestionMapper.deleteByFillEmptyId(id);
    }

    // 读入代码片段文件
    public static String readFileToString(String filePath) throws IOException {
        File file = new File(filePath);
        StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append(System.lineSeparator());
            }
        }
        return sb.toString();
    }

    // 向这个服务器的写入代码片段的txt文件，文件名为编号
    public static void saveToFile(String content, String fileName, String address) {
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(address + fileName);
            fileWriter.write(content);

        } catch (IOException e) {
            System.out.println("发生错误：" + e.getMessage());
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    System.out.println("无法关闭文件写入器：" + e.getMessage());
                }
            }
        }
    }
}
